package com.company.genealogy.web.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.company.genealogy.common.result.ApiResponse;
import com.company.genealogy.web.dto.BatchSpouseUpdateDTO;
import com.company.genealogy.web.entity.Member;
import com.company.genealogy.web.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import com.alibaba.excel.EasyExcel;
import com.company.genealogy.web.vo.MemberExportVO;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.excel.EasyExcelFactory;
import com.company.genealogy.web.vo.MemberImportVO;
import com.company.genealogy.common.constant.ApiCodeEnum;
import com.company.genealogy.web.mapper.MemberSpouseMapper;
import com.company.genealogy.web.entity.MemberSpouse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.company.genealogy.web.vo.MemberTreeNodeVO;
import com.company.genealogy.web.vo.MemberSpouseVO;
import com.company.genealogy.web.vo.StatisticsVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 家族成员管理控制器
 * 
 * 提供家族成员的增删改查、树形结构展示、配偶关系管理、
 * 数据导入导出等功能的REST API接口。
 * 
 * 主要功能：
 * - 成员基本信息管理
 * - 族谱树形结构展示和搜索
 * - 成员关系维护（父子、配偶）
 * - 数据统计和分析
 * - 批量数据导入导出
 * - 权限控制和数据安全
 * 
 * @author chenzhixiang
 * @version 1.0
 * @since 2024-01-01
 */
@RestController
@RequestMapping("/api/v1/members")
public class MemberController {
    
    /**
     * 日志记录器
     */
    private static final Logger log = LoggerFactory.getLogger(MemberController.class);

    /**
     * 成员服务接口
     */
    @Autowired
    private MemberService memberService;

    /**
     * 成员配偶关系数据访问对象
     */
    @Autowired
    private MemberSpouseMapper memberSpouseMapper;

    /**
     * 分页查询成员列表
     * 
     * 支持按姓名、性别、家族ID、分支ID等条件进行筛选查询，
     * 使用数据库分页查询以提高性能。
     * 
     * @param page 页码，默认为1
     * @param size 每页大小，默认为10
     * @param clanId 家族ID，可选
     * @param branchId 分支ID，可选
     * @param name 成员姓名，支持模糊查询，可选
     * @param gender 性别，可选
     * @return 分页的成员列表数据
     */
    @GetMapping
    public ApiResponse<IPage<Member>> list(@RequestParam(defaultValue = "1") int page,
                                           @RequestParam(defaultValue = "10") int size,
                                           @RequestParam(required = false) Long clanId,
                                           @RequestParam(required = false) Long branchId,
                                           @RequestParam(required = false) String name,
                                           @RequestParam(required = false) String gender) {
        /**
         * 使用数据库分页查询，提高性能
         * 避免一次性加载大量数据到内存中
         */
        IPage<Member> result = memberService.getMemberListWithPage(page, size, name, gender, clanId, branchId);
        return ApiResponse.success(ApiCodeEnum.SUCCESS, result);
    }

    /**
     * 新增家族成员
     * 
     * 创建新的家族成员记录，包含基本信息如姓名、性别、出生日期等。
     * 配偶关系需要后续通过专门的接口进行维护。
     * 
     * @param member 成员信息对象
     * @return 创建成功的成员信息
     */
    @PostMapping
    public ApiResponse<Member> create(@RequestBody Member member) {
        memberService.save(member);
        /**
         * 配偶关系由前端调用batch-update接口维护
         * 这样可以确保数据的一致性和完整性
         */
        return ApiResponse.success(ApiCodeEnum.SUCCESS, member);
    }

    /**
     * 获取成员详细信息
     * 
     * 根据成员ID获取成员的完整信息，包括基本信息、家族信息、分支信息等。
     * 
     * @param id 成员ID
     * @return 成员详细信息
     */
    @GetMapping("/{id}")
    public ApiResponse<Member> getMemberDetail(@PathVariable Long id) {
        Member member = memberService.getMemberDetail(id);
        return ApiResponse.success(member);
    }
    
    /**
     * 获取成员的子女列表（按排序）
     * 
     * 根据成员ID获取其所有子女，按照childOrder字段进行排序。
     * 用于族谱树形结构的展示和成员关系管理。
     * 
     * @param id 成员ID
     * @return 子女列表，按排序字段排列
     */
    @GetMapping("/{id}/children")
    public ApiResponse<List<Member>> getMemberChildren(@PathVariable Long id) {
        List<Member> children = memberService.getChildrenByParentId(id);
        return ApiResponse.success(children);
    }
    
    /**
     * 更新子女排序
     * 
     * 修改指定成员的子女排序号，用于调整族谱树中成员的显示顺序。
     * 
     * @param id 成员ID
     * @param childOrder 新的排序号
     * @return 更新操作是否成功
     */
    @PutMapping("/{id}/child-order")
    public ApiResponse<Boolean> updateChildOrder(@PathVariable Long id, @RequestParam Integer childOrder) {
        boolean result = memberService.updateChildOrder(id, childOrder);
        return ApiResponse.success(result);
    }
    
    /**
     * 重新排序同一父母下的所有子女
     * 
     * 批量调整同一父母下所有子女的排序，用于族谱树的拖拽排序功能。
     * 
     * @param parentId 父成员ID
     * @param childIds 子女ID列表，按期望的顺序排列
     * @return 重新排序操作是否成功
     */
    @PutMapping("/{parentId}/children/reorder")
    public ApiResponse<Boolean> reorderChildren(@PathVariable Long parentId, @RequestBody List<Long> childIds) {
        boolean result = memberService.reorderChildren(parentId, childIds);
        return ApiResponse.success(result);
    }

    /**
     * 获取树形结构的子节点（懒加载）
     * 
     * 支持族谱树的懒加载功能，根据父节点ID获取其直接子节点。
     * 用于优化大数据量时的前端展示性能。
     * 
     * @param parentId 父节点ID，为null时获取根节点
     * @return 子节点列表
     */
    @GetMapping("/tree/children")
    public ApiResponse<List<MemberTreeNodeVO>> getTreeChildren(@RequestParam(required = false) Long parentId) {
        List<MemberTreeNodeVO> children = memberService.getChildrenTreeNodes(parentId);
        return ApiResponse.success(ApiCodeEnum.SUCCESS, children);
    }

    /**
     * 搜索树形结构中的成员
     * 
     * 在族谱树中搜索指定姓名的成员，支持模糊匹配。
     * 返回匹配的成员及其在树中的位置信息。
     * 
     * @param name 搜索的成员姓名
     * @return 匹配的成员节点列表
     */
    @GetMapping("/tree/search")
    public ApiResponse<List<MemberTreeNodeVO>> searchTreeByName(@RequestParam String name) {
        List<MemberTreeNodeVO> result = memberService.searchTreeByName(name);
        return ApiResponse.success(ApiCodeEnum.SUCCESS, result);
    }

    /**
     * 获取成员的配偶列表
     * 
     * 根据成员ID获取其所有配偶信息，包括配偶的基本信息和关系信息。
     * 
     * @param id 成员ID
     * @return 配偶信息列表
     */
    @GetMapping("/{id}/spouses")
    public ApiResponse<List<MemberSpouseVO>> getMemberSpouses(@PathVariable Long id) {
        try {
            List<MemberSpouseVO> spouses = memberService.getMemberSpouses(id);
            return ApiResponse.success(spouses);
        } catch (Exception e) {
            return ApiResponse.fail("获取配偶信息失败");
        }
    }
    
    /**
     * 为成员添加配偶
     * 
     * 为指定成员添加新的配偶关系，包括配偶的基本信息和关系类型。
     * 
     * @param spouseVO 配偶信息对象
     * @return 添加操作是否成功
     */
    @PostMapping("/spouses")
    public ApiResponse<Boolean> addMemberSpouse(@RequestBody MemberSpouseVO spouseVO) {
        try {
            boolean result = memberService.addMemberSpouse(spouseVO);
            return result ? ApiResponse.success(true) : ApiResponse.fail("添加配偶信息失败");
        } catch (Exception e) {
            e.printStackTrace();
            return ApiResponse.fail("添加配偶信息失败");
        }
    }
    
    /**
     * 更新成员配偶信息
     * 
     * 修改指定配偶关系的信息，包括配偶基本信息和关系类型。
     * 
     * @param id 配偶关系ID
     * @param spouseVO 更新的配偶信息对象
     * @return 更新操作是否成功
     */
    @PutMapping("/spouses/{id}")
    public ApiResponse<Boolean> updateMemberSpouse(@PathVariable Long id, @RequestBody MemberSpouseVO spouseVO) {
        try {
            spouseVO.setId(id);
            boolean result = memberService.updateMemberSpouse(spouseVO);
            return result ? ApiResponse.success(true) : ApiResponse.fail("更新配偶信息失败");
        } catch (Exception e) {
            return ApiResponse.fail("更新配偶信息失败");
        }
    }
    
    /**
     * 删除成员配偶关系
     * 
     * 删除指定的配偶关系记录，同时会清理相关的数据关联。
     * 
     * @param id 配偶关系ID
     * @return 删除操作是否成功
     */
    @DeleteMapping("/spouses/{id}")
    public ApiResponse<Boolean> deleteMemberSpouse(@PathVariable Long id) {
        try {
            boolean result = memberService.deleteMemberSpouse(id);
            return result ? ApiResponse.success(true) : ApiResponse.fail("删除配偶信息失败");
        } catch (Exception e) {
            e.printStackTrace();
            return ApiResponse.fail("删除配偶信息失败");
        }
    }
    
    // 新增：增强的树形结构接口（包含配偶信息）
    @GetMapping("/tree/enhanced/children")
    public ApiResponse<List<MemberTreeNodeVO>> getEnhancedTreeChildren(
            @RequestParam(required = false) Long parentId,
            @RequestParam(required = false) Long branchId) {
        try {
            List<MemberTreeNodeVO> nodes = memberService.getEnhancedTreeNodes(parentId, branchId);
            return ApiResponse.success(nodes);
        } catch (Exception e) {
            return ApiResponse.fail("获取树形数据失败");
        }
    }
    
    @GetMapping("/tree/enhanced/search")
    public ApiResponse<List<MemberTreeNodeVO>> searchEnhancedTreeByName(@RequestParam String name) {
        try {
            List<MemberTreeNodeVO> nodes = memberService.searchEnhancedTreeByName(name);
            return ApiResponse.success(nodes);
        } catch (Exception e) {
            return ApiResponse.fail("搜索失败");
        }
    }
    
    // 新增：统计接口
    @GetMapping("/statistics")
    public ApiResponse<StatisticsVO> getStatistics() {
        try {
            StatisticsVO statistics = memberService.getStatistics();
            return ApiResponse.success(statistics);
        } catch (Exception e) {
            return ApiResponse.fail("获取统计数据失败");
        }
    }

    // 新增：调试接口 - 查看所有成员
    @GetMapping("/debug/all")
    public ApiResponse<List<Member>> getAllMembers() {
        try {
            List<Member> members = memberService.list();
            return ApiResponse.success(members);
        } catch (Exception e) {
            return ApiResponse.fail("获取成员列表失败");
        }
    }

    // 编辑成员
    @PutMapping("/{id}")
    public ApiResponse<Void> update(@PathVariable Long id, @RequestBody Member member) {
        member.setId(id);
        memberService.updateById(member);
        // 配偶关系由前端调用batch-update接口维护
        return ApiResponse.success(ApiCodeEnum.SUCCESS, null);
    }

    // 删除成员
    @DeleteMapping("/{id}")
    public ApiResponse<Void> delete(@PathVariable Long id) {
        // 先删除多对多配偶关系
        memberSpouseMapper.delete(new QueryWrapper<MemberSpouse>().eq("member_id", id).or().eq("spouse_id", id));
        memberService.removeById(id);
        return ApiResponse.success(ApiCodeEnum.SUCCESS, null);
    }

    // 导出成员Excel
    @GetMapping("/export")
    public void exportMembers(HttpServletResponse response,
                             @RequestParam(required = false) String name,
                             @RequestParam(required = false) String gender,
                             @RequestParam(required = false) Long clanId,
                             @RequestParam(required = false) Long branchId) throws Exception {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("成员列表", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        // 查询数据
        List<Member> memberList = memberService.getMemberList(name, gender, clanId, branchId);
        // 转换为导出VO
        List<MemberExportVO> exportList = MemberExportVO.fromEntityList(memberList);
        EasyExcel.write(response.getOutputStream(), MemberExportVO.class).sheet("成员列表").doWrite(exportList);
    }

    // 导入成员Excel
//    @PreAuthorize("hasRole('ADMIN')")
    @PostMapping("/import")
    public ApiResponse<Void> importMembers(@RequestParam("file") MultipartFile file) throws Exception {
        List<MemberImportVO> importList = EasyExcelFactory.read(file.getInputStream())
                .head(MemberImportVO.class)
                .sheet()
                .doReadSync();
        memberService.importMembers(importList);
        return ApiResponse.success(ApiCodeEnum.SUCCESS, null);
    }

    @PutMapping("/{memberId}/parent")
    public ApiResponse<Object> updateMemberParent(@PathVariable Long memberId, @RequestParam Long newParentId) {
        try {
            log.info("更新父节点关系: memberId={}, newParentId={}", memberId, newParentId);
            
            // 验证新父节点是否存在
            Member newParent = memberService.getById(newParentId);
            if (newParent == null) {
                log.warn("新父节点不存在: newParentId={}", newParentId);
                return ApiResponse.fail("新父节点不存在");
            }
            
            // 验证不能将节点拖拽到自己的子节点下
            boolean isChild = memberService.isChildOf(memberId, newParentId);
            log.info("检查子节点关系: memberId={}, newParentId={}, isChild={}", memberId, newParentId, isChild);
            
            if (isChild) {
                log.warn("尝试将节点拖拽到自己的子节点下: memberId={}, newParentId={}", memberId, newParentId);
                return ApiResponse.fail("不能将节点拖拽到自己的子节点下");
            }
            
            // 更新父节点关系
            Member member = memberService.getById(memberId);
            if (member == null) {
                log.warn("成员不存在: memberId={}", memberId);
                return ApiResponse.fail("成员不存在");
            }
            
            member.setFatherId(newParentId);
            memberService.updateById(member);
            
            log.info("父节点关系更新成功: memberId={}, newParentId={}", memberId, newParentId);
            return ApiResponse.success("父节点关系更新成功");
        } catch (Exception e) {
            log.error("更新成员父节点失败: memberId={}, newParentId={}", memberId, newParentId, e);
            return ApiResponse.fail("更新父节点失败");
        }
    }

    @PostMapping("/../member-spouse/batch-update")
    public ApiResponse<Void> batchUpdateSpouse(@RequestBody BatchSpouseUpdateDTO dto) {
        // 1. 先删除该成员所有配偶关系
        memberSpouseMapper.delete(new QueryWrapper<MemberSpouse>().eq("member_id", dto.getMemberId()));
        // 2. 批量插入新配偶关系
        if (dto.getSpouseIds() != null) {
            for (Long spouseId : dto.getSpouseIds()) {
                MemberSpouse ms = new MemberSpouse();
                ms.setMemberId(dto.getMemberId());
                ms.setSpouseId(spouseId);
                ms.setRelationType("spouse");
                ms.setSortOrder(0);
                memberSpouseMapper.insert(ms);
            }
        }
        return ApiResponse.success();
    }
}